using System;

namespace HEFramework
{
    /// <summary>
    ///
    /// 时间执行器
    /// 
    /// ----------------------------------------
    /// 作者 hep
    /// 创建时间：2023-11-29 14:32:36
    /// ----------------------------------------
    /// </summary>
    public class TimeRunner : Singleton<TimeRunner>, ISingletonAwake, ISingletonUpdate
    {
        private int timeZone;
        private long serverMinusClientTime;
        private long frameTime;

        private DateTime dt1970;
        private DateTime dt;

        public int TimeZone
        {
            get { return this.timeZone; }
            set
            {
                this.timeZone = value;
                dt = dt1970.AddHours(TimeZone);
            }
        }

        /// <summary>
        /// ping消息会设置该值，原子操作
        /// </summary>
        public long ServerMinusClientTime => serverMinusClientTime;

        /// <summary>
        /// 当前时间戳
        /// </summary>
        public long FrameTime => frameTime;


        public void Awake()
        {
            this.dt1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            this.dt = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            this.frameTime = this.ClientNow();
        }

        public void Update()
        {
            // 赋值long型是原子操作，线程安全
            this.frameTime = this.ClientNow();
        }

        /// <summary> 
        /// 根据时间戳获取时间 
        /// </summary>  
        public DateTime ToDateTime(long _timeStamp)
        {
            return dt.AddTicks(_timeStamp * 10000);
        }

        /// <summary>
        /// 客户端时间戳
        /// </summary>
        /// <returns></returns>
        public long ClientNow()
        {
            return (DateTime.UtcNow.Ticks - this.dt1970.Ticks) / 10000;
        }

        /// <summary>
        /// 服务端时间戳
        /// </summary>
        /// <returns></returns>
        public long ServerNow()
        {
            return ClientNow() + this.serverMinusClientTime;
        }

        public long ClientFrameTime()
        {
            return this.frameTime;
        }

        public long ServerFrameTime()
        {
            return this.frameTime + this.serverMinusClientTime;
        }

        public long Transition(DateTime _d)
        {
            return (_d.Ticks - dt.Ticks) / 10000;
        }
    }
}